'''
Created on 2010-12-22

@author: zarra
'''
import cherrypy
from _direct import *

from _direct import DirectRouter,DirectProviderDefinition
from cherrypy import expose
import json

import traceback
import StringIO

class NoSuchAction(DirectException):
    pass

class ActionAlreadyInstall(DirectException):
    pass

class CherrypyDirectRouter(DirectRouter):
    def __init__(self,real_object):
        super(CherrypyDirectRouter,self).__init__(real_object)
    def __call__(self,body):
        try:
            result=self._call(body)
        #except DirectException,e:
        #    raise e
        except:
            fp = StringIO.StringIO()
            traceback.print_exc(file=fp)
            message = fp.getvalue()
            result ={'success':False,'data':message}
            raise cherrypy.HTTPError(500,message)
        cherrypy.response.headers['Content-Type'] = 'application/json'
        return result
        
class CherrypyDirectProviderDefinition(DirectProviderDefinition):
    def __init__(self,routercls,url,ns=None,timeout=None):
        super(CherrypyDirectProviderDefinition,self).__init__(routercls,url,ns=None,timeout=None)
    
    def __call__(self):
        cherrypy.response.headers['Content-Type'] = 'application/javascript'
        return self.render()

class ActionManager(object):
    def __init__(self,root='/direct'): 
        self.direct_base_url   = root
        #cherrypy.tree.mount(self,root)
        self.service_base_url  = 'service'
        self.provider_base_url = 'provider'
        self.services  = {}
        self.prividers = {}
    def action_url(self,name):
        service_url = "/%s/%s"%(self.service_base_url,name)
        #provider_url = "%s/%s"%(self.provider_base_url,name)
        return service_url#,provider_url
    def remove_app(self,app,d):
        if  d.has_key(app):
            del d[app]
        else:
            raise NoSuchAction('NoSuchAction:%s'%app)
    
    def register_action(self,action,name=None):
        if name == None:
            name = action.__class__.__name__
    
        service_url = self.action_url(name)
        service_url=self.direct_base_url+service_url
        service  = CherrypyDirectRouter(action)
        provider = CherrypyDirectProviderDefinition(action,service_url)    
        if  not  self.services.has_key(name) :
            self.services[name]=service
            self.prividers[name]=provider
        else:
            raise ActionAlreadyInstall('Action name:%s  has already been installed! '%name)
    
    def remove_action(self,name):
        self.remove_app(name,self.services)
        self.remove_app(name,self.prividers)
    @expose    
    def api(self):  
        fp = StringIO.StringIO()
        for k,v in self.prividers.items():
            fp.write("%s\n"%v())
        page = fp.getvalue()
        fp.close()
        return page
    @expose
    def service(self,*actions):
        request_url = '/'.join(actions)
        if len(actions)<1:
            raise cherrypy.HTTPError(404,'page %s not found!'%request_url)
        try:
            action = actions[0]
            if self.services.has_key(action):
                s = self.services[action]
            else:
                raise cherrypy.HTTPError(404,'page %s not found!'%request_url)
            data=cherrypy.request.body.read()
            return s(data)
        except:
            fp = StringIO.StringIO()
            traceback.print_exc(file=fp)
            message = fp.getvalue()
            fp.close()
            raise cherrypy.HTTPError(500,message)
  